import * as vscode from 'vscode';

import { DictArray, DictWordMap, DictTranslatedWordMap, DictSynonymMap, DictItem, BaseWordMap, WordsType } from '../typing';


export default function gatherData(dictArray: DictArray) {
  // 各项单词组
  const words = generateAllWords(dictArray);
  // 各项单词组Map
  const wordMaps = generateAllWordMaps(dictArray);
  // 近义词正则
  const synonymsRegExp = new RegExp([...words.synonyms].join('|'), 'ig');

  return {
    dictArray,
    ...words,
    ...wordMaps,
    synonymsRegExp,
  };
}

function generateAllWordMaps(dictArray: DictArray) {
  let dictWordMap: DictWordMap = {};
  let dictTranslatedWordMap: DictTranslatedWordMap = {};
  let dictSynonymMap: DictSynonymMap = {};



  if (Array.isArray(dictArray) && dictArray.length > 0) {
    try {
      dictWordMap = generateAnyWordMapByPropName(dictArray, 'words');
      dictTranslatedWordMap = generateAnyWordMapByPropName(dictArray, 'translatedWords');
      dictSynonymMap = generateAnyWordMapByPropName(dictArray, 'synonyms');
    } catch (ex) {
      vscode.window.showErrorMessage('projectDictionary 文件格式错误');
    }
  }

  return {
    dictWordMap,
    dictTranslatedWordMap,
    dictSynonymMap,
  };
}

function generateAllWords(dictArray: DictArray) {
  let words: Set<string> = new Set();
  let translatedWords: Set<string> = new Set();
  let synonyms: Set<string> = new Set();

  if (Array.isArray(dictArray) && dictArray.length > 0) {
    try {
      words = generateAnyWordsByWordsType(dictArray, 'words');
      translatedWords = generateAnyWordsByWordsType(dictArray, 'translatedWords');
      synonyms = generateAnyWordsByWordsType(dictArray, 'synonyms');
    } catch (ex) {
      vscode.window.showErrorMessage('projectDictionary 文件格式错误');
    }
  }

  const allWords = new Set([
    ...words,
    ...translatedWords,
    ...synonyms
  ]);

  return {
    words,
    translatedWords,
    synonyms,
    allWords,
  };
}

function generateAnyWordMapByPropName(dictArray: DictArray, propName: keyof DictItem) {
  return dictArray.reduce((prev, dictItem) => {
    dictItem[propName].forEach(word => {
      prev[word] = prev[word]
        ? Array.isArray(prev[word])
          ? [...prev[word] as DictItem[], dictItem]
          : [prev[word] as DictItem, dictItem]
        : dictItem;
    });

    return prev;
  }, {} as BaseWordMap);
}

function generateAnyWordsByWordsType(dictArray: DictArray, wordsType: WordsType) {
  return dictArray.reduce((prev, dictItem) => {
    dictItem[wordsType].forEach(word => {
      prev.add(word);
    });

    return prev;
  }, new Set<string>());
}
